<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<title>火焰和烟雾效果</title>
		
		<script type="text/javascript" src="js/three.min.js"></script>
		<script type="text/javascript" src="js/OrbitControls.js" ></script>
		<script type="text/javascript" src="js/Stats.js" ></script>
		<script type="text/javascript" src="js/dat.gui.min.js" ></script>
		<script type="text/javascript" src="js/Fire.js" ></script>
		<script type="text/javascript" src="js/tween.min.js" ></script>
		<script type="text/javascript" src="js/physi.js" ></script>
		<style>
			body{
				background: url(img/bg.jpg) no-repeat top center fixed; overflow: hidden;
				background-size: 100%;
				padding: 0;
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<script>
			// 实际代码
			var scene, renderer, camera; // 三大件
			var controls, stats, clock; // 辅助组件
			var arrowBodyMesh, smokeParticles = []; // 箭体网格对象和烟雾数组
			// 箭体图片路径
			var arrowPath = "img/arrow.png";
			// 烟雾图片路径
			var smokePath = "img/cloud.png";
			function init() {
				// 创建clock
				clock = new THREE.Clock();
				// 创建场景
				scene=new THREE.Scene();
				// 创建渲染器
				renderer=new THREE.WebGLRenderer({
					antialias:true,
					alpha:true
				});
				renderer.setClearColor(0x000000, 0.0);
				renderer.setSize(window.innerWidth,window.innerHeight);
				renderer.setPixelRatio(window.devicePixelRatio);
				document.body.appendChild(renderer.domElement);
				// 创建透视相机
				camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
				camera.position.set(0,0,30);
				
				// 辅助移动视角
				// controls=new THREE.OrbitControls(camera,renderer.domElement);
				// controls.enableDamping=true;
				// controls.minDistance=1;
				// controls.maxDistance=500;
				
				scene.add(new THREE.AmbientLight(0XCCCCCC, 0.5));
				
				var pointLight=new THREE.PointLight(0xffffff, 0.8);
				pointLight.position.set(0, 10, 40);
				scene.add(pointLight);
			}
			
			var fire, fire1;
			function initModel(){
				// var helper = new THREE.GridHelper(1000, 50);
				// scene.add(helper);
				
				// 尾焰
				var plane=new THREE.PlaneBufferGeometry(15,30,1);
				fire = new THREE.Fire(plane,{
					textureWidth:1024,
					textureHeight:1024,
					debug:false,
					color1: new THREE.Color(0xffffff),
					color2: new THREE.Color(0xffc159),
					color3: new THREE.Color(0xe69bb1),
					windVector: new THREE.Vector2(0, -1.2),
					colorBias: 0.92,
					burnRate: 1.19,
					diffuse: 5,
					viscosity: 0.2,
					expansion: -3,
					swirl: 8,
					drag: 0.17,
					airSpeed: 23,
					speed: 390,
					massConservation: false
				});
				// fire = new THREE.Fire(plane,{
				// 	textureWidth:512,
				// 	textureHeight:512,
				// 	debug:false,
				// 	color1: new THREE.Color(0xffffff),
				// 	color2: new THREE.Color(0xffc159),
				// 	color3: new THREE.Color(0xe69bb1),
				// 	windVector: new THREE.Vector2(0, -2),
				// 	colorBias: 0.61,
				// 	burnRate: 1.73,
				// 	diffuse: 1.3,
				// 	viscosity: 0.25,
				// 	expansion: 0,
				// 	swirl: 50,
				// 	drag: 0.35,
				// 	airSpeed: 11,
				// 	speed: 531,
				// 	massConservation: false
				// });
				fire.addSource(0.5, 0.6, 0.1, 1.0, 0.0, -2.0);
				fire.addSource(0.62, 0.6, 0.1, 1.0, 0.0, -2.0);
				fire.addSource(0.38, 0.6, 0.1, 1.0, 0.0, -2.0);
				fire.position.y = firePosition;
				fire.position.z = -10;
				// fire.rotateX(Math.PI);//绕x轴旋转π/4
				scene.add(fire);
			
				// 烟雾
				var smokeTexture = THREE.ImageUtils.loadTexture(smokePath);
				var smokeMaterial = new THREE.MeshLambertMaterial({
					map: smokeTexture,
					transparent: true
				});
				var smokeGeo = new THREE.PlaneGeometry(30, 30);
				for (p = 0; p < smokeCount; p++) {
					var particle = new THREE.Mesh(smokeGeo, smokeMaterial);
					// particle.position.set((p-10)*5, -28+Math.abs(p-10)*2, -5);
					particle.position.set(0, firePosition-8, -5);
					// particle.position.set((p-10)*5, -28+Math.abs(p-10)*3, -5);
					particle.rotation.z = Math.random() * 360;
					// particle.rotateX(Math.PI);//绕x轴旋转π/4
					scene.add(particle);
					smokeParticles.push(particle);
				}
				
				// 箭体
				var arrowPlane=new THREE.PlaneBufferGeometry(10,25,1);
				// var geometry = new THREE.CubeGeometry( 10, 10, 10);
				var material = new THREE.MeshPhongMaterial({
					map: THREE.ImageUtils.loadTexture(arrowPath),
					transparent: true
					});
				arrowBodyMesh = new THREE.Mesh(arrowPlane, material);
				arrowBodyMesh.position.y = (firePosition + 18.7);
				arrowBodyMesh.position.z = -10;
				scene.add(arrowBodyMesh);
			}
			
			var smokeCount = 20; // 组成烟雾的对象数量
			var firePosition = -30; // 尾焰y轴位置
			
			/**
			 * 飞行动画
			 */
			var tweenFireFlySlow, tweenArrowFlySlow, tweenFireFlyFast, tweenArrowFlyFast;
			function initTween(distance) {
				// // 尾焰起飞-慢
				// tweenFireFlySlow = new TWEEN.Tween(fire.position)
				//         .to( { y: (firePosition + 28.7) }, 2500 ).repeat(0).start();
				// tweenFireFlySlow.easing(TWEEN.Easing.Quadratic.In);
				
				// // 箭体起飞-慢
				// tweenArrowFlySlow = new TWEEN.Tween(arrowBodyMesh.position)
				//         .to( { y: (47.4 + firePosition) }, 2500 ).repeat(0).start();
				// tweenArrowFlySlow.easing(TWEEN.Easing.Quadratic.In);
				
				// // 尾焰起飞-快
				// tweenFireFlyFast = new TWEEN.Tween(fire.position)
				//         .to( { y: (firePosition + 68.7) }, 1000 ).repeat(0);
				// tweenFireFlyFast.easing(TWEEN.Easing.Elastic.In);
				
				// // 箭体起飞-快
				// tweenArrowFlyFast = new TWEEN.Tween(arrowBodyMesh.position)
				//         .to( { y: (87.4 + firePosition) }, 1000 ).repeat(0);
				// tweenArrowFlyFast.easing(TWEEN.Easing.Elastic.In);
				
				// 尾焰起飞-慢
				tweenFireFlySlow = new TWEEN.Tween(fire.position)
				        .to( { y: (firePosition + 68.7) }, 5500 ).repeat(0).start();
				tweenFireFlySlow.easing(TWEEN.Easing.Quadratic.In);
				
				// 箭体起飞-慢
				tweenArrowFlySlow = new TWEEN.Tween(arrowBodyMesh.position)
				        .to( { y: (87.4 + firePosition) }, 5500 ).repeat(0).start();
				tweenArrowFlySlow.easing(TWEEN.Easing.Quadratic.In);
				
				// 烟雾运动
				for (var p = 0; p < smokeCount; p++) {
					new TWEEN.Tween(smokeParticles[p].position)
						.to( { x: (p-10)*5 }, 3000 ).repeat(0).start()
						.easing(TWEEN.Easing.Quadratic.Out);
					new TWEEN.Tween(smokeParticles[p].position)
						.to( { y: -26+Math.abs(p-10)*3 }, 2000 ).repeat(0).start()
						.easing(TWEEN.Easing.Quadratic.Out);
						
					new TWEEN.Tween(smokeParticles[p].position)
						.to( { z: Math.abs(p-10)*3 }, 2000 ).repeat(0).start()
						.easing(TWEEN.Easing.Quadratic.Out);
				}
				
				// tweenFireFlySlow.chain(tweenFireFlyFast);
				// tweenArrowFlySlow.chain(tweenArrowFlyFast);
			}
			
			window.onresize = function (){
				camera.aspect=window.innerWidth/window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth,window.innerHeight);
			}
			
			function render(){
				renderer.render(scene,camera);
			}
			
			function animate(){
				if (!isStop) {
					// controls.update();
					TWEEN.update();
					delta = clock.getDelta();
					evolveSmoke();
					requestAnimationFrame(animate);
					render();
				}
			}
			
			// 烟雾旋转
			function evolveSmoke() {
			    var sp = smokeParticles.length;
			    while (sp--) {
					if (sp%2==0) { // 偶数逆时针旋转
						smokeParticles[sp].rotation.z += (delta * 0.1);
					} else { // 奇数顺时针旋转
						smokeParticles[sp].rotation.z += -(delta * 0.1);
					}
			    }
			}
			
			/**
			 * three.js动画准备
			 */
			function threeReady(){
				init();
				initModel();
			}
			
			/**
			 * three.js动画开始
			 */
			function threeStart() {
				// 允许动画循环
				isStop = false;
				initTween();
				animate();
			}
			
			/**
			 * 元素归位，动画循环停止
			 */
			var isStop = false; // 是否停止动画nd
			function threeEnd() {
				// 尾焰归位
				fire.position.set(0, firePosition, -10);
				// 烟雾归位
				for (var p = 0; p < smokeCount; p++) {
					smokeParticles[p].position.set(0, firePosition-8, -5);
				}
				// 箭体归位
				arrowBodyMesh.position.set(0, firePosition + 18.7, -10);
				// 动画循环停止
				isStop = true;
			}
			
			threeReady();
			threeStart();
		</script>
	</body>
</html>
